Closures in JavaScript
In JavaScript you sometimes need so called "closures" to encapsulate scope.
Lets say you want to make a pattern for each texture:
// Create patterns for(var i=0; i < textures.length; i++) { textures[i].onload = function(i) { pattern[i] = ctx.createPattern(textures[i], 'repeat'); } }
The code loops the texture array and when each texture has loaded a pattern is created.
But there is a problem! Once a texture has loaded, the for loop has already finished and the variable i passed to the onload function will always be textures.length!
To solve this you need to use a closure. It might look something like this:
// Create patterns for(var i=0; i < textures.length; i++) { textures[i].onload = (function(index) { return function() { pattern[index] = ctx.createPattern(textures[index], 'repeat'); }; } })(i);
This can be hard to understand. But it's possible to rewrite the code to make sense!
What the closure does is to create a function and then pass variable i to it, that becomes the local variable index
You can rewrite it like this:
for(var i=0; i < textures.length; i++) { createPattern(i); } function createPattern(i) { textures[i].onload = function() { pattern[i] = ctx.createPattern(textures[i], 'repeat'); } }
So next time you need to make a closure, put the code that needs to run right away in a function!
Async Closure
var button = document.createElement("button"); button.appendChild(document.createTextNode("Click me")); document.body.appendChild(button); button.onclick = function click() { button.appendChild(document.createTextNode(" more!")); }
Even though the click function is async (run later) it will have access to the button variable!
Written by Johan Zetterberg April 16th 2015.